package gicom;

import gicom.config.ORBConfig;
import gicom.config.ObjectConfig;
import gicom.config.POAConfig;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.management.ManagementFactory;
import java.net.URL;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javax.management.ObjectName;

public class GenericServer extends Thread implements GenericServerMBean {

    private File directory;
    private GenericManager genericManager;
    public static GenericServer defaultGenericServer;
    
    private FileFilter fileFilter;
    private Set<String> files;
    
    public GenericServer (File directory) throws Exception {
        if (!directory.isDirectory()) throw new Exception(directory + " is not a directory");
        this.directory = directory;
        this.genericManager = new GenericManager();
        
        this.fileFilter = new FileFilter() {
            public boolean accept(File pathname) {
                String name = pathname.getName();
                if (name.endsWith("~")) return false;
                if (name.endsWith("_tmp") && new File(GenericServer.this.directory, name.substring(0, name.length() - 4)).exists()) return false;
                if (!name.startsWith("orb_") && !name.startsWith("poa_") && !name.startsWith("object_")) return false;
                return true;
            }
        };
        
        this.files = new HashSet<String>();
        
        ManagementFactory.getPlatformMBeanServer().registerMBean(this, new ObjectName("gicom.GenericServer:type=" + GenericServer.class.toString() + ",name=" + this.hashCode()));
    }
    
    public File getDirectory() {
        return directory;
    }
    
    public GenericManager getGenericManager() {
        return genericManager;
    }
    
    public void addConfigFile (String str) throws Exception {
        URL url = new URL(str);
        File file = new File(getDirectory(), url.getFile());
        if (file.exists()) file.delete();
        InputStream uis = url.openStream();
        FileOutputStream fos = new FileOutputStream(file);
        int value = uis.read();
        while (value != -1) {
            fos.write(value);
            value = uis.read();
        }
        uis.close();
        fos.close();
    }
    
    public void removeConfigFile (String str) throws Exception {
        new File(directory, str).delete();
    }
    
    public String[] getConfigFile () throws Exception {
        return directory.list();
    }
    
    public void addJarFile (String str) throws Exception {
        URL url = new URL(str);
        File file = new File(getDirectory(), "jar/" + url.getFile());
        if (file.exists()) file.delete();
        InputStream uis = url.openStream();
        FileOutputStream fos = new FileOutputStream(file);
        int value = uis.read();
        while (value != -1) {
            fos.write(value);
            value = uis.read();
        }
        uis.close();
        fos.close();
    }
    
    public void removeJarFile (String str) throws Exception {
        new File(directory, "jar/" + str).delete();
    }
    
    public String[] getJarFile () throws Exception {
        return new File(directory, "jar").list();
    }
    
    public static void main(String[] args) {
        try {
            defaultGenericServer = new GenericServer(new File(args[0]));
            defaultGenericServer.start();
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
    @Override
    public void run() {
        try {
            while (true) {
                String id = null;
                File[] f = directory.listFiles(fileFilter);
                Set<String> temp = new HashSet<String>();
                temp.addAll(files);
                for (int i = 0; i < f.length; i++) {
                    id = f[i].getName();
                    if (id.endsWith("_tmp")) id = id.substring(0, id.length() - 4);
                    temp.remove(id);
                    if(!files.contains(id)) {
                        try {
                            if (id.startsWith("orb_")) getGenericManager().createORB(new ORBConfig(id.substring(4)));
                            else if (id.startsWith("poa_")) getGenericManager().createPOA(new POAConfig(id.substring(4)));
                            else if (!getGenericManager().objectExists(id.substring(7))) getGenericManager().createObject(new ObjectConfig(id.substring(7)));
                            files.add(id);
                        } catch (Exception e) {
                            files.remove(id);
                            System.out.println("Warning : Error while loading the file " + id);
                        }
                    }
                }
                Iterator<String> iterator = temp.iterator();
                while (iterator.hasNext()) {
                    id = iterator.next();
                    try {
                        if(id.startsWith("orb_")) getGenericManager().destroyORB(id.substring(4));
                        else if(id.startsWith("poa_")) getGenericManager().destroyPOA(id.substring(4));
                        else  if (getGenericManager().objectExists(id.substring(7))) getGenericManager().destroyObject(id.substring(7));
                        files.remove(id);
                    } catch (Exception e) {
                        files.remove(id);
                        System.out.println("Warning : Error while destroying the file " + id);
                    }
                }
                sleep(1000);
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    
}
